# coding:utf-8
import base64
import datetime
import hashlib
import hmac
import uuid
import requests
import json
from tjob.initialize.setup_envs import (
    PROTOCOL,
    ENDPOINT,
    ACCESS_KEY_ID,
    ACCESS_KEY_SECRET,
)


def to_string(s, encoding="utf-8"):
    if s is None:
        return s

    if isinstance(s, bytes):
        return s.decode(encoding)
    else:
        return str(s)


def _get_canonicalized_resource(pathname, query):
    if query is None or len(query) <= 0:
        return pathname
    resource = "%s?" % pathname
    query_list = sorted(list(query))
    for key in query_list:
        if query[key] is not None:
            if query[key] == "":
                s = "%s&" % key
            else:
                s = "%s=%s&" % (key, to_string(query[key]))
            resource += s
    return resource[:-1]


def get_string_to_sign(method, url_path, headers, query):
    """使用请求信息生成待签名的字符串"""

    accept = "" if headers.get("accept") is None else headers.get("accept")
    content_md5 = (
        "" if headers.get("content-md5") is None else headers.get("content-md5")
    )
    content_type = (
        "" if headers.get("content-type") is None else headers.get("content-type")
    )
    date = "" if headers.get("date") is None else headers.get("date")

    header = "%s\n%s\n%s\n%s\n%s\n" % (
        method,
        accept,
        content_md5,
        content_type,
        date,
    )
    canon_headers = _get_canonicalized_headers(headers)
    canon_resource = _get_canonicalized_resource(url_path, query)
    sign_str = header + canon_headers + canon_resource
    return sign_str


def get_roasignature(string_to_sign, secret):
    """生成签名：使用HMAC-256生成签名，然后通过base64输出签名字符串。"""
    hash_val = hmac.new(
        secret.encode("utf-8"), string_to_sign.encode("utf-8"), hashlib.sha1
    ).digest()
    signature = base64.b64encode(hash_val).decode("utf-8")
    return signature


def _get_canonicalized_headers(headers):
    """将请求头排序后，获取“x-acs-”作为前缀按字母序排序后拼接。
    注意，按RFC2616, HTTP 请求头的名称是大小写不敏感的。
    """

    canon_keys = []
    for k in headers:
        if k.startswith("x-acs-"):
            canon_keys.append(k)
    canon_keys = sorted(canon_keys)
    canon_header = ""
    for k in canon_keys:
        canon_header += "%s:%s\n" % (k, headers[k])
    return canon_header


def do_request(
    api_product, api_method, api_path, api_query=None, api_body=None, verbose=False
):
    """根据请求信息，生成认证信息，发送请求给到后端服务"""

    ts = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
    signature_nonce = str(uuid.uuid4())
    headers = {
        "x-acs-signature-method": "HMAC-SHA1",
        "date": ts,
        "x-acs-signature-nonce": signature_nonce,
        # 必须
        "x-pai-product": api_product,
        # 必须
        "accept": "application/json",
    }
    if api_body is not None:
        headers["content-type"] = "application/json"

    api_url = f"{PROTOCOL}://{ENDPOINT}{api_path}"
    # 使用请求信息，生成请求使用的签名(signature)，然后生成对应认证信息，
    # 在请求头里传递给到服务(authorization)
    string_to_sign = get_string_to_sign(
        method=api_method,
        url_path=api_path,
        headers=headers,
        query=api_query,
    )
    signature = get_roasignature(
        string_to_sign=string_to_sign, secret=ACCESS_KEY_SECRET
    )
    headers["authorization"] = f"acs {ACCESS_KEY_ID}:{signature}"

    resp = requests.request(
        method=api_method,
        url=api_url,
        params=api_query,
        headers=headers,
        json=api_body,
        timeout=100,
        # verify=False,
    )
    content = json.loads(resp.content)
    if verbose:
        print(resp.status_code)
        print(json.dumps(content, indent=4))
    return resp
